package com.woniuxy.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.admin.client.GoodsFeignClient;
import com.woniuxy.admin.entity.*;
import com.woniuxy.admin.exception.AdminException;
import com.woniuxy.admin.exception.LoginException;
import com.woniuxy.admin.exception.PawnShopException;
import com.woniuxy.admin.exception.RegisterException;
import com.woniuxy.admin.form.*;
import com.woniuxy.admin.mapper.*;
import com.woniuxy.admin.service.*;
import com.woniuxy.admin.dto.AdminAccountDto;
import com.woniuxy.admin.dto.AdminAccountPageDto;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.woniuxy.openfeign.util.Result;
import com.woniuxy.redis.util.RedisKey;
import com.woniuxy.redis.util.RedisUtil;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ...
 * @since 2024年05月22日
 */
@Service
public class AdminAccountServiceImpl extends ServiceImpl<AdminAccountMapper, AdminAccount> implements AdminAccountService {


    @Resource
    private AdminInfoMapper adminInfoMapper;
    @Resource
    private AdminRoleMapper adminRoleMapper;
    @Resource
    private AdminAccountRoleMapper adminAccountRoleMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private AdminRoleService adminRoleService;
    @Resource
    private AdminInfoService adminInfoService;
    @Resource
    private PawnShopService pawnShopService;
    @Resource
    private PawnShopMapper pawnShopMapper;
    @Resource
    private GoodsFeignClient goodsFeignClient;


    /**
     * 注册管理员
     * @param form
     * @throws InterruptedException
     */
    @Override
    public void registAdmin(RegistAdminForm form) throws InterruptedException {
        List<AdminAccount> list = this.list();
        if(list!=null&&list.size()>0){
            for (AdminAccount adminAccount : list) {
                if(adminAccount.getAdminName().equals(form.getAdminName())){
                    throw new AdminException(10003,"用户名已存在");
                }
                if(adminAccount.getAdminPhone().equals(form.getAdminPhone())){
                    throw new AdminException(10003,"手机号已存在");
                }
            }
        }
        AdminAccount adminAccount = BeanUtil.toBean(form, AdminAccount.class);
        adminAccount.setAdminPass("123456");
        adminAccount.setState(0);
        this.save(adminAccount);
        AdminInfo adminInfo = BeanUtil.toBean(form, AdminInfo.class);
        adminInfo.setNickName("admin");
        adminInfo.setAccountId(adminAccount.getAccountId());
        adminInfo.setAdminHeader("xxxxxxx");
        adminInfo.setAdminWorkDate(LocalDate.now());
        adminInfoMapper.insert(adminInfo);
    }

    /**
     * 管理员登录
     * @param form
     * @return
     */
    @Override
    public AdminAccountDto adminLogin(AdminLoginForm form) {
    QueryWrapper<AdminAccount>wrapper=new QueryWrapper<>();
    wrapper.eq("admin_name",form.getAdminName());
    AdminAccount adminAccount = this.getOne(wrapper);
    if(adminAccount==null) throw new LoginException(20001,"用户名不存在");
    if(!adminAccount.getAdminPass().equals(form.getAdminPass())) throw new LoginException(20002,"密码错误");
    if(adminAccount.getState()!=0) throw new LoginException(20003,"账户已被禁用");
        AdminAccountDto dto = new AdminAccountDto();
        dto.setAccountId(adminAccount.getAccountId());
        dto.setAdminName(adminAccount.getAdminName());
        return dto;
    }

    /**
     * 管理员验证码登录
     * @param form
     * @return
     */
    @Override
    public AdminAccountDto adminCodeLogin(AdminCodeLoginForm form) {
        if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getAdminPhone()))) {
            if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getAdminPhone())))) >= 5) {
                throw new RegisterException(10002, "验证码已错5次,请重新发送");
            }
        }
        if (!form.getAdminCode().equals(redisUtil.get(RedisKey.AdminLoginCodeKey(form.getAdminPhone())))) {
            if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getAdminPhone()))) {
                redisUtil.insr(RedisKey.codeErrorNumber(form.getAdminPhone()));
                if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getAdminPhone())))) >= 5) {
                    redisUtil.del(RedisKey.AdminLoginCodeKey(form.getAdminPhone()));
                }
            } else {
                redisUtil.set(RedisKey.codeErrorNumber(form.getAdminPhone()), "1", 5 * 60);
            }
            throw new RegisterException(10001, "验证码错误");
        }
        QueryWrapper<AdminAccount>wrapper=new QueryWrapper<>();
        wrapper.eq("admin_phone",form.getAdminPhone());
        AdminAccount adminAccount = this.getOne(wrapper);
        if(adminAccount==null){
            throw new LoginException(10002,"还未注册,请先注册");
        }
        if(adminAccount.getState()!=0) throw new LoginException(10001,"管理员账号被禁用");
        AdminAccountDto dto = new AdminAccountDto();
        dto.setAccountId(adminAccount.getAccountId());
        dto.setAdminName(adminAccount.getAdminName());
        return dto;
    }

    /**
     * 查询所有管理员信息
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Page<AdminAccountPageDto> loadAllAdminAccount(Integer pageNum, Integer pageSize,String condition) {
       Page <AdminAccount >page=new Page<>(pageNum,pageSize);
       QueryWrapper<AdminAccount>wrapper=new QueryWrapper<>();
       if(condition!=null&&!condition.equals("")){
           wrapper.like("admin_phone",condition).or();
           wrapper.like("admin_name",condition);
       }
       this.page(page, wrapper);
       List<AdminAccountPageDto>list=new ArrayList<>();
       if(page.getRecords()!=null&&page.getRecords().size()>0){
           for (AdminAccount adminAccount : page.getRecords()) {
               AdminAccountPageDto adminAccountPageDto = BeanUtil.toBean(adminAccount, AdminAccountPageDto.class);
               AdminInfo adminInfo = adminInfoMapper.selectOne(new QueryWrapper<AdminInfo>().eq("account_id", adminAccount.getAccountId()));
               BeanUtil.copyProperties(adminInfo,adminAccountPageDto);
               String s = adminRoleService.loadAllRoleNameByAccountId(adminAccount.getAccountId());
               adminAccountPageDto.setRole(s);
               list.add(adminAccountPageDto);
           }
       }
       Page<AdminAccountPageDto>pages=new Page<>();
       pages.setPages(page.getPages());
       pages.setSize(page.getSize());
       pages.setCurrent(page.getCurrent());
       pages.setTotal(page.getTotal());
       pages.setRecords(list);
       return pages;
    }

    /**
     * 根据角色Id 查出账号集合
     * @param roleId
     * @return
     */
    @Override
    public List<Integer> selectAccountsByRoleId(Integer roleId) {
        List<AdminRole> adminRoles = adminRoleMapper.selectList(new QueryWrapper<AdminRole>());
        if(adminRoles==null||adminRoles.size()==0) throw new AdminException(10005,"角色不存在");
       if (!adminRoles.stream().map(a->a.getRoleId()).collect(Collectors.toList()).contains(roleId)) {
       throw new AdminException(10006,"角色不存在");
       }
        List<AdminAccountRole> adminAccountRoles = adminAccountRoleMapper.selectList(new QueryWrapper<AdminAccountRole>().eq("role_id", roleId));
       if(adminAccountRoles==null||adminAccountRoles.size()==0)
        throw new AdminException(10008,"该角色还没有绑定账号");
        List<Integer> accounts = adminAccountRoles.stream().map(a -> a.getAccountId()).collect(Collectors.toList());
        return accounts;
    }

    /**
     * 发送管理员登录验证码
     * @param adminPhone
     */
    @Override
    public void sendAdminLoginCode(String adminPhone) {
        if (redisUtil.hasKey(RedisKey.phoneCodeOneMinuteKey(adminPhone))) {
            throw new RegisterException(10004, "1分钟内不能重复发送");
        }
        if (redisUtil.hasKey(RedisKey.fiveMssageKey(adminPhone))) {
            int num = Integer.parseInt(redisUtil.get(RedisKey.fiveMssageKey(adminPhone)));
            if (num >= 5) {
                throw new RegisterException(10005, "发送次数达到上限");
            }
        }
        //手机号存入消息队列中 由消费者来监听处理
        rabbitTemplate.convertAndSend("login_code_queue",adminPhone);
    }

    /**
     * 发送管理修改手机短信
     *
     * @param accountId
     * @param adminPhone
     * @return
     */
    @Override
    public void sendAdminUpdatePhone(Integer accountId, String adminPhone) {
        AdminAccount adminAccount = this.getOne(new QueryWrapper<AdminAccount>().eq("account_id", accountId).eq("admin_phone", adminPhone));
        if(adminAccount==null) throw new AdminException(10001,"用户账号和手机不相匹配");
        if (redisUtil.hasKey(RedisKey.phoneCodeOneMinuteKey(adminPhone))) {
            throw new AdminException(40001, "1分钟内不能重复发送");
        }
        if (redisUtil.hasKey(RedisKey.fiveMssageKey(adminPhone))) {
            int num = Integer.parseInt(redisUtil.get(RedisKey.fiveMssageKey(adminPhone)));
            if (num >= 5) {
                throw new AdminException(40001, "发送次数达到上限");
            }
        }
        QueryWrapper<AdminAccount> wrapper = new QueryWrapper<AdminAccount>();
        wrapper.eq("admin_phone", adminPhone);
        AdminAccount adminAccount1 = this.getOne(wrapper);
        if (adminAccount1 == null) {
            throw new AdminException(60001, "手机号不存在");
        }
        //手机号存入消息队列中 由消费者来监听处理
        rabbitTemplate.convertAndSend("admin_update_phone_code_queue",adminPhone);
    }

    /**
     * 发送管理修改新手机短信
     *
     * @param accountId
     * @param adminPhone
     * @return
     */
    @Override
    public void sendAdminUpdateNewPhone(Integer accountId, String adminPhone) {
        AdminAccount adminAccount = this.getOne(new QueryWrapper<AdminAccount>().eq("admin_phone", adminPhone));
        if(adminAccount!=null) throw new AdminException(10002,"手机号已被绑定");
        if (redisUtil.hasKey(RedisKey.phoneCodeOneMinuteKey(adminPhone))) {
            throw new AdminException(40001, "1分钟内不能重复发送");
        }
        if (redisUtil.hasKey(RedisKey.fiveMssageKey(adminPhone))) {
            int num = Integer.parseInt(redisUtil.get(RedisKey.fiveMssageKey(adminPhone)));
            if (num >= 5) {
                throw new AdminException(40001, "发送次数达到上限");
            }
        }
        //手机号存入消息队列中 由消费者来监听处理
        rabbitTemplate.convertAndSend("admin_update_new_phone_code_queue",adminPhone);
    }

    /**
     * 管理修改手机号
     *
     * @param accountId
     * @param form
     * @return
     */
    @Override
    public void adminUpdatePhone(Integer accountId, AdminUpdatePhoneForm form) {
        if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getOldPhone()))) {
            if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getOldPhone())))) >= 5) {
                throw new LoginException(10002, "验证码已错5次,请重新发送");
            }
        }
        if (!form.getOldPhoneCode().equals(redisUtil.get(RedisKey.AdminUpdatePhoneCodeKey(form.getOldPhone())))) {
            if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getOldPhone()))) {
                redisUtil.insr(RedisKey.codeErrorNumber(form.getOldPhone()));
                if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getOldPhone())))) >= 5) {
                    redisUtil.del(RedisKey.AdminUpdatePhoneCodeKey(form.getOldPhone()));
                }
            } else {
                redisUtil.set(RedisKey.codeErrorNumber(form.getOldPhone()), "1", 5 * 60);
            }
            throw new LoginException(10001, "老手机验证码错误");
        }

        if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getNewPhone()))) {
            if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getNewPhone())))) >= 5) {
                throw new LoginException(10002, "验证码已错5次,请重新发送");
            }
        }
        if (!form.getNewPhoneCode().equals(redisUtil.get(RedisKey.AdminUpdateNewPhoneCodeKey(form.getNewPhone())))) {
            if (redisUtil.hasKey(RedisKey.codeErrorNumber(form.getNewPhone()))) {
                redisUtil.insr(RedisKey.codeErrorNumber(form.getNewPhone()));
                if ((Integer.parseInt(redisUtil.get(RedisKey.codeErrorNumber(form.getNewPhone())))) >= 5) {
                    redisUtil.del(RedisKey.AdminUpdateNewPhoneCodeKey(form.getNewPhone()));
                }
            } else {
                redisUtil.set(RedisKey.codeErrorNumber(form.getNewPhone()), "1", 5 * 60);
            }
            throw new LoginException(10001, "新手机验证码错误");
        }
        AdminAccount adminAccount = this.getById(accountId);
        adminAccount.setAdminPhone(form.getNewPhone());
        this.updateById(adminAccount);

    }

    /**
     * 修改密码
     *
     * @param accountId
     * @param form
     * @return
     */
    @Override
    public void adminUpdatePass(Integer accountId, AdminUpdatePassForm form) {
        AdminAccount adminAccount = this.getById(accountId);
        if(adminAccount==null) throw new AdminException(10001,"用户不存在");

        if (!adminAccount.getAdminPass().equals(form.getOldPass())) {
            throw new AdminException(10001,"老密码错误");
        }
        adminAccount.setAdminPass(form.getNewPass());
        this.updateById(adminAccount);
    }

    /**
     * 根据角色Id 查询账号详情
     * @param roleId
     * @return
     */
    @Override
    public List<AdminAccountPageDto> selectAccountInfoByRoleId(Integer roleId) {
        List<Integer> accounts = this.selectAccountsByRoleId(roleId);
        List<AdminAccountPageDto> list=new ArrayList<>();
        if(accounts!=null&&accounts.size()>0){
            for (Integer accountId : accounts) {
                AdminAccountPageDto adminInfoByAccountId = adminInfoService.findAdminInfoByAccountId(accountId);
                list.add(adminInfoByAccountId);
            }
        }
        return list;
    }

    /**
     * 根据用户名查找账户信息
     * @param adminName 用户名
     * @return 管理员信息
     */
    @Override
    public AdminAccount selectAccountByAdminName(String adminName) {
        QueryWrapper<AdminAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("admin_name",adminName);
        return getOne(wrapper);
    }

    /**
     * 更新管理员状态
     *
     * @param accountId
     * @param state
     */
    @Override
    public void updateAdminAccountState(Integer accountId, Integer state) throws Exception {
        AdminAccount account = this.getById(accountId);
        if(account==null){
            throw new AdminException(10008,"账号不存在");
        }
        Integer roleId = adminRoleService.selectRoleId(accountId);
        if(roleId==1) throw new AdminException(10001,"不能禁用超级管理员");
        //店长
        if(roleId==3){
            //禁用
            if(state==1){
                //查询对应门店
                PawnShop shop = pawnShopService.findShopByAccountId(accountId);
                if(shop!=null){
                    throw new PawnShopException(10001,"该店长已绑定请先更换门店店长");
                }
//                //查询未绑定店长
//                List<AdminAccountPageDto> dtos = adminInfoService.selectAllShopBoss();
//                if(dtos==null||dtos.size()==0) throw new AdminException(10001,"暂时不能禁用");
//                //更换门店店长
//                AdminAccountPageDto dto = dtos.get(0);
//                shop.setShopBossId(dto.getAccountId());
//                shop.setContact(dto.getRealName());
//                pawnShopMapper.updateById(shop);
//                goodsFeignClient.updateProcessByBoss(accountId,dto.getAccountId());
            }
        }else {
            String key="";
            String value="";
            Integer score=0;
            //鉴定师
            if(roleId==5){
                //禁用
                if(state==1){
                    //删除redis
                   redisUtil.zrem(RedisKey.jiandingshi(),accountId+"");
                   key=RedisKey.jiandingshi();
                   value=account+"";
                    Double zscore = redisUtil.zscore(RedisKey.jiandingshi(), accountId + "");
                    if(zscore!=null) {
                        zscore = Double.valueOf(Math.floor(zscore));
                        score=Integer.parseInt(zscore.toString());
                    }else {
                        score = 0;
                    }
                }else {
                    //启用新增
                    redisUtil.zadd(RedisKey.jiandingshi(),accountId+"",0);
                }
            }
            //评估师
            if(roleId==6){
                if(state==1){
                    //删除redis
                    redisUtil.zrem(RedisKey.pinggushi(),accountId);
                    key=RedisKey.pinggushi();
                    value=account+"";
                    Double zscore = redisUtil.zscore(RedisKey.pinggushi(), accountId + "");
                    score=Integer.parseInt(zscore.toString());
                }else {
                    //启用新增
                    redisUtil.zadd(RedisKey.pinggushi(),accountId+"",0);
                }
            }
            if(state==1){
                Result result = goodsFeignClient.updateProcessByAccountId(accountId);
                if(result.getCode()!=200){
                    redisUtil.zadd(key,value,score);
                    throw new AdminException(10001,result.getMessage());
                }
            }
        }
        account.setState(state);
        this.updateById(account);
    }


}
